package com.youlu.campus.component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONException;
import com.github.qcloudsms.SmsSingleSender;
import com.github.qcloudsms.SmsSingleSenderResult;
import com.github.qcloudsms.httpclient.HTTPException;
import com.youlu.campus.base.exception.BusinessException;

import com.youlu.campus.common.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.TimeUnit;

/**
 * 短信工具类
 *
 * @author: zhuhuaiqi
 * @date: 2018/9/11 14:21
 */
@Slf4j
@Component
public class SmsUtil {


    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 短信应用SDK AppID
     */
    @Value("${sys.sms.appId}")
    private int appid;
    /**
     * AppKey
     */
    @Value("${sys.sms.appkey}")
    private String appkey;
    /**
     * 用户验证码存储前缀
     */
    @Value("${sys.sms.prefix}")
    private String prefix;

    /**
     * 发送登录短信验证码
     *
     * @param phone
     */
    public boolean sendLoginSms(String smsSign, Integer tempalteId, String phone) {

        return sendSms(smsSign, phone, tempalteId);
    }

    /**
     * 验证登陆短信
     *
     * @param phone
     * @param code
     * @return
     */
    public boolean checkLoginSms(String phone, String code) {
        log.info(":>>> 开始验证登陆短信:{},code:{}", phone, code);
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(code)) {
            log.error(":>>> 参数错误:手机号或验证码为空");
            throw new BusinessException("手机号或验证码为空");
        }
        String str = TimeUtils.getCurrentYMD(new Date());
        String key = String.format(prefix, phone);
        String codeStr = redisTemplate.opsForValue().get(key);
        if (StringUtils.isBlank(codeStr)) {
            log.error(":>>> 验证码过期");
            if (str.equals(code)) {
                log.error(":>>> 手机号:{} 通过超级验证码验证:{}", phone, str);
                return true;
            }
            throw new BusinessException("验证码过期");
        }
        if (codeStr.equals(code)) {
            return true;
        } else {
            if (str.equals(code)) {
                log.error(":>>> 手机号:{} 通过超级验证码验证:{}", phone, str);
                return true;
            }
        }

        return false;

    }

    /**
     * 发送短信信息
     *
     * @param phone
     * @param templateId
     * @param params
     * @return
     */
    public boolean sendSmsWithContent(String smsSign, String phone, int templateId, String... params) {
        try {

            SmsSingleSender ssender = new SmsSingleSender(appid, appkey);
            SmsSingleSenderResult result = ssender.sendWithParam("86", phone,
                    templateId, params, smsSign, "", "");
            log.info("发送短信返回结果：{}", JSON.toJSONString(result));
            if (result == null || result.result != 0) {
                log.error(":>>> 短信发送结果为空,或是返回码不是成功");
                return false;
            }

        } catch (HTTPException e) {
            log.error("发送短信请求异常，异常信息：{}", e);
            return false;
        } catch (JSONException e) {
            log.error("发送短信Json解析异常，异常信息：{}", e);
            return false;
        } catch (IOException e) {
            log.error("发送短信网络IO错误，异常信息：{}", e);
            return false;
        }


        return true;
    }

    /**
     * 发送验证码
     *
     * @param phone
     * @param templateId
     * @return
     */
    private boolean sendSms(String smsSign, String phone, int templateId) {
        try {

            //生成六位随机码
            String randNum = getRandNum(6);

            String[] params = {randNum};
            String[] phoneNumbers = {phone};
            SmsSingleSender ssender = new SmsSingleSender(appid, appkey);
            SmsSingleSenderResult result = ssender.sendWithParam("86", phoneNumbers[0],
                    templateId, params, smsSign, "", "");
            log.info("发送短信返回结果：{}", result);
            if (result == null || result.result != 0) {
                return false;
            }
            //将手机号和随机码存储到redis
            this.setRedisCode(phone, randNum);

        } catch (HTTPException e) {
            log.error("发送短信请求异常，异常信息：{}", e.getMessage());
            return false;
        } catch (JSONException e) {
            log.error("发送短信Json解析异常，异常信息：{}", e.getMessage());
            return false;
        } catch (IOException e) {
            log.error("发送短信网络IO错误，异常信息：{}", e.getMessage());
            return false;
        }


        return true;
    }


    private void setRedisCode(String phone, String code) {
        String key = String.format(prefix, phone);
        redisTemplate.opsForValue().set(key, code);
        //十分钟失效时间
        redisTemplate.expire(key, 5, TimeUnit.MINUTES);

        log.info("设置用户{}验证码信息成功:{}", phone, code);
    }

    public String getRandNum(int charCount) {
        String charValue = "";
        for (int i = 0; i < charCount; i++) {
            char c = (char) (randomInt(0, 10) + '0');
            charValue += String.valueOf(c);
        }
        return charValue;
    }

    private int randomInt(int from, int to) {
        Random r = new Random();
        return from + r.nextInt(to - from);
    }

}
